package com.csii.adhoc.info.user.serviceImpl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.csii.adhoc.exception.ParamValidityException;
import com.csii.adhoc.id.UidGenerator;
import com.csii.adhoc.info.depart.DepartPo;
import com.csii.adhoc.info.depart.service.DepartService;
import com.csii.adhoc.info.post.PostPo;
import com.csii.adhoc.info.post.service.PostService;
import com.csii.adhoc.info.role.RolePo;
import com.csii.adhoc.info.role.service.RoleService;
import com.csii.adhoc.info.user.BatchUpdateUserVo;
import com.csii.adhoc.info.user.UserPo;
import com.csii.adhoc.info.user.UserVo;
import com.csii.adhoc.info.user.mapper.UserMapper;
import com.csii.adhoc.info.user.service.UserService;
import com.csii.adhoc.util.ParamCheckUtils;
import com.csii.adhoc.util.encrypt.DESUtil;
import com.csii.adhoc.util.encrypt.ShiroKit;
import com.csii.common.constant.CommonConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @description: 用户接口实现类
 * @author: panChuanJiang
 * @create: 2021-01-26 09:05
 */
@Service("userService")
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, UserPo> implements UserService {
    @Resource
    private UserMapper userMapper;
    @Resource
    private UidGenerator uidGenerator;
    @Resource
    private RoleService roleService;
    @Resource
    private DepartService departService;
    @Resource
    private PostService postService;

    @Override
    @Transactional
    public void userMaintain(UserPo userPo, String optMode) {
        switch (optMode) {
            case CommonConstant.OPT_MODE_ADD:
                userPo.setCreatedBy(userPo.getUpdatedBy())
                        .setCreatedDt(userPo.getUpdatedDt());
                insertOneUser(userPo);
                break;
            case CommonConstant.OPT_MODE_DELETE:
                deleteUserByPrimaryKey(userPo.getUserId());
                break;
            case CommonConstant.OPT_MODE_UPDATE:
                updateUserByPrimaryKey(userPo);
                break;
            default:
                log.error("optMode值不合法:" + optMode);
                throw new ParamValidityException("optMode值不合法:" + optMode);
        }
    }

    @Override
    @Transactional
    public void updateUserInfoByMq(UserPo userPo) {
        UserPo user = userMapper.selectUserByUserName(userPo.getName());
        if (user != null) {
            userPo.setUserId(user.getUserId());
            userMapper.updateUserSelective(userPo);
        } else {
            userPo.setUserId(uidGenerator.getUID() + "");
            userMapper.insertOneUser(userPo);
        }
    }

    @Override
    public List<UserPo> selectListUser(UserPo userPo) {
        userPo = userPo == null ? new UserPo() : userPo;
        return userMapper.selectPageUserPo(userPo);
    }

    @Override
    public UserPo selectUser(String usrId) {
        return userMapper.selectUserByPrimaryKey(usrId);
    }

    @Override
    public UserPo selectUserByUserName(String usrName) {
        return userMapper.selectUserByUserName(usrName);
    }

    @Override
    public IPage<UserPo> selectPageUser(Page<UserPo> page, UserPo userPo) {
        IPage<UserPo> userPoIPage = userMapper.selectPageUserPo(page, userPo);
        setInfoNamesFromIds(userPoIPage.getRecords());
        return userPoIPage;
    }

    @Transactional
    public void insertOneUser(UserPo userPo) {
        UserPo user = selectUserByUserName(userPo.getUsername());
        if (user != null) {
            throw new ParamValidityException(String.format("username已存在:%s", userPo.getUsername()));
        }
        long uid = uidGenerator.getUID();
        String randomSalt = ShiroKit.getRandomSalt(10);
        String password = ShiroKit.md5("123456", randomSalt);
        userPo.setUserId(uid + "")
                .setPassword(password)
                .setSalt(randomSalt);
        userMapper.insertOneUser(userPo);
    }

    @Transactional
    public void updateUserByPrimaryKey(UserPo userPo) {
        if (StringUtils.isEmpty(userPo.getUserId())) {
            throw new ParamValidityException("userId值不合法:" + userPo.getUserId());
        }
        userMapper.updateUserByPrimaryKey(userPo);
    }

    @Transactional
    public void deleteUserByPrimaryKey(String userId) {
        if (StringUtils.isEmpty(userId)) {
            throw new ParamValidityException("userId值不合法:" + userId);
        }
        userMapper.deleteUserByPrimaryKey(userId);
    }

    @Transactional
    @Override
    public void updateUserClearPostId(String postId) {
        userMapper.updateUserClearPostId(postId);
    }

    @Transactional
    @Override
    public void updateUserClearRoleId(String roleId) {
        userMapper.updateUserClearRoleId(roleId);
    }

    @Transactional
    @Override
    public void updateListUserRoleOrPost(BatchUpdateUserVo batchUpdateUserVo) {
        Set<String> ids = new HashSet<>();
        if (!ParamCheckUtils.checkListIsEmpty(batchUpdateUserVo.getUserIds())) {
            ids.addAll(batchUpdateUserVo.getUserIds());
        }
        String postId = batchUpdateUserVo.getPostId();
        String roleId = batchUpdateUserVo.getRoleId();
        List<UserPo> userPos = selectListUser(null);
        if (!StringUtils.isEmpty(postId)) {
            userPos.forEach(x -> {
                String itemPost = Optional.ofNullable(x.getPostId()).orElse("");//防止空指针异常
                if (ids.contains(x.getUserId())) {
                    if (!itemPost.contains(postId)) {
                        itemPost = "".equals(itemPost) ? postId : itemPost + "," + postId;
                    }
                } else {//没用则删除
                    if (itemPost.contains(postId)) {
                        itemPost = itemPost.replaceAll(",?" + postId, "");
                    }
                }
                x.setPostId(itemPost);
            });
        }
        if (!StringUtils.isEmpty(roleId)) {
            userPos.forEach(x -> {
                String itemRole = Optional.ofNullable(x.getRole()).orElse("");//防止空指针异常
                if (ids.contains(x.getUserId())) {
                    if (!itemRole.contains(roleId)) {
                        itemRole = "".equals(itemRole) ? roleId : itemRole + "," + roleId;
                    }
                } else {//没用则删除
                    if (itemRole.contains(roleId)) {
                        itemRole = itemRole.replaceAll(",?" + roleId, "");
                    }
                }
                x.setRole(itemRole);
            });
        }
        userMapper.updateListUser(userPos);
    }

    @Transactional
    @Override
    public void updateUserClearDepartId(String departId) {
        userMapper.updateUserClearDepartId(departId);
    }

    @Override
    public void updateUserPassword(UserVo vo) {
        String password = vo.getPassword();
        UserPo userOld = selectUser(vo.getUserId());
        String newPassword = null;
        String inputOldPassword = null;
        try {
            newPassword = ShiroKit.md5(DESUtil.decryption(password, "38442065" + userOld.getUsername()), userOld.getSalt());
            inputOldPassword = ShiroKit.md5(DESUtil.decryption(vo.getOldPassword(), "38442065" + userOld.getUsername()), userOld.getSalt());
        } catch (Exception e) {
            throw new RuntimeException("加密异常");
        }
        if (!inputOldPassword.equals(userOld.getPassword())) {
            throw new ParamValidityException("旧密码输入错误");
        }
        vo.setPassword(newPassword);
        userMapper.updateUserSelective(vo);
    }

    private void setInfoNamesFromIds(List<UserPo> users) {
        //从用户的角色、部门、职务的id、获取响应的名称给前台
        List<RolePo> roles = roleService.selectListRole(null);
        Map<String, String> roleMap = roles.stream().collect(Collectors.toMap(RolePo::getRoleId, RolePo::getName));
        List<PostPo> posts = postService.selectListPost(null);
        Map<String, String> postMap = posts.stream().collect(Collectors.toMap(PostPo::getPostId, PostPo::getName));
        List<DepartPo> departs = departService.selectListDepart(null);
        Map<String, String> departMap = departs.stream().collect(Collectors.toMap(DepartPo::getDepartId, DepartPo::getName));
        users.forEach(x -> {
            String roleIds = x.getRole();
            if (!StringUtils.isEmpty(roleIds)) {
                String[] split = roleIds.split(",");
                StringBuilder roleName = new StringBuilder();
                Arrays.stream(split).forEach(y -> {
                    if (roleMap.get(y) != null) {
                        roleName.append(roleMap.get(y)).append(",");
                    }
                });
                if (roleName.length() > 0) {
                    x.setRoleName(roleName.substring(0, roleName.length() - 1));
                }
            }
            String postIds = x.getPostId();
            if (!StringUtils.isEmpty(postIds)) {
                String[] split = postIds.split(",");
                StringBuilder postName = new StringBuilder();
                Arrays.stream(split).forEach(y -> {
                    if (postMap.get(y) != null) {
                        postName.append(postMap.get(y)).append(",");
                    }
                });
                if (postName.length() > 0) {
                    x.setPostName(postName.substring(0, postName.length() - 1));
                }
            }
            String departIds = x.getDepart();
            if (!StringUtils.isEmpty(departIds)) {
                String[] split = departIds.split(",");
                StringBuilder departName = new StringBuilder();
                Arrays.stream(split).forEach(y -> {
                    if (departMap.get(y) != null) {
                        departName.append(departMap.get(y)).append(",");
                    }
                });
                if (departName.length() > 0) {
                    x.setDepartName(departName.substring(0, departName.length() - 1));
                }
            }
        });
    }
}
